package net.sf.ivyide.idea;

import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import net.sf.ivyide.ContentRootTemplate;
import net.sf.ivyide.IvyEnvironmentInfo;
import net.sf.ivyide.MyAntEnvironmentInfo;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.regex.Pattern;

public class IvyPluginConfiguration {
    private JTable m_projectRootsTable;

    private MyAntEnvironmentInfo m_environmentInfo;
    private JButton m_addButton;
    private JButton m_deleteButton;
    private JFormattedTextField m_projectInitTarget;
    private TextFieldWithBrowseButton m_antFilePath;
    private JFormattedTextField m_ivyInitTargetTextField;
    private JFormattedTextField m_ivyBuildListRefTextField;
    private JPanel m_rootPanel;
    private JFormattedTextField m_artifactTypeFilter;
    private JTable m_globalContentRootsTable;
    private JButton m_addGlobalRoot;
    private JButton m_deleteGlobalRoot;
    private JTextField m_compilerOutputPathTemplateTextField;
    private JTextField m_compilerOutputPathTemplateForTestsTextField;


    public IvyEnvironmentInfo getValidInfoFromGui() {
        return ProgressUtilities.executeRunnableWithProgress(getComponent(), "Checking ivy setup...", "Unable to initialize IVY environment",
                new ProgressAwareCallable<IvyEnvironmentInfo>() {
                    public IvyEnvironmentInfo call(ProgressIndicator progressIndicator) throws Exception {
                        m_environmentInfo.setIvyBuildListReference(m_ivyBuildListRefTextField.getText());
                        m_environmentInfo.setIvyInitTarget(m_ivyInitTargetTextField.getText());
                        m_environmentInfo.setArtifactFilterString(m_artifactTypeFilter.getText());
                        m_environmentInfo.setIvyInitBuildFile(new File(m_antFilePath.getText()));
                        m_environmentInfo.setProjectInitTarget(m_projectInitTarget.getText());
                        m_environmentInfo.setCompilerOutputPathForTestsTemplate(m_compilerOutputPathTemplateForTestsTextField.getText());
                        m_environmentInfo.setCompilerOutputPathTemplate(m_compilerOutputPathTemplateTextField.getText());
                        m_environmentInfo.validate();
                        return m_environmentInfo;
                    }
                });
    }

    public IvyPluginConfiguration(MyAntEnvironmentInfo info, Project project) {
        m_environmentInfo = info != null ? info.clone() : new MyAntEnvironmentInfo();
        FileChooserDescriptor fileChooserDescriptor = new FileChooserDescriptor(true, false, false, false, false, false);
        m_antFilePath.addBrowseFolderListener("Choose build file", "Choosing a build file", null, fileChooserDescriptor);

        if (m_environmentInfo.getIvyInitBuildFile() != null) {
            m_antFilePath.setText(m_environmentInfo.getIvyInitBuildFile().getPath());
        } else {
            m_antFilePath.setText(project.getBaseDir().getPath());
        }
        m_ivyInitTargetTextField.setText(m_environmentInfo.getIvyInitTarget());
        m_artifactTypeFilter.setText(m_environmentInfo.getArtifactFilterString());
        m_projectInitTarget.setText(m_environmentInfo.getProjectInitTarget());
        m_compilerOutputPathTemplateForTestsTextField.setText(m_environmentInfo.getCompilerOutputPathForTestsTemplate());
        m_compilerOutputPathTemplateTextField.setText(m_environmentInfo.getCompilerOutputPathTemplate());
        m_ivyBuildListRefTextField.setText(m_environmentInfo.getIvyBuildListReference());

        List<ContentRootTemplate> moduleRoots = m_environmentInfo.getProjectRootTemplates();
        initTemplateRootTableEditor(moduleRoots, m_projectRootsTable, m_addButton, m_deleteButton);
        moduleRoots = m_environmentInfo.getGlobalRootTemplates();
        initTemplateRootTableEditor(moduleRoots, m_globalContentRootsTable, m_addGlobalRoot, m_deleteGlobalRoot);

    }

    private void initTemplateRootTableEditor(final List<ContentRootTemplate> templates, final JTable table, JButton addButton, JButton deleteButton) {
        final AbstractTableModel tableModel = new ContentRootTemplateTableModel(templates);
        table.setModel(tableModel);

        configureColumn(table, 0, "Content Root");
        configureColumn(table, 1, "Main java");
        configureColumn(table, 2, "Test java");
        configureColumn(table, 3, "Main resource");
        configureColumn(table, 4, "Test resource");
        configureColumn(table, 5, "Included subdirectories regexp");
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                templates.add(new ContentRootTemplate("MyRoot"));
                tableModel.fireTableDataChanged();
            }
        });
        deleteButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                ContentRootTemplate contentRootTemplate = templates.get(table.getSelectedRow());
                templates.remove(contentRootTemplate);
                tableModel.fireTableDataChanged();
            }
        });
    }

    private void configureColumn(JTable table, int index, String columnName) {
        TableColumn column = table.getColumnModel().getColumn(index);
        column.setHeaderValue(columnName);
        column.setCellEditor(table.getDefaultEditor(String.class));
        column.setCellRenderer(table.getDefaultRenderer(String.class));
    }

    public JComponent getComponent() {
        return m_rootPanel;
    }

    private class ContentRootTemplateTableModel extends AbstractTableModel {
        private final List<ContentRootTemplate> m_roots;

        public ContentRootTemplateTableModel(List<ContentRootTemplate> roots) {
            m_roots = roots;
        }

        public int getRowCount() {
            return m_roots.size();  //To change body of implemented methods use File | Settings | File Templates.
        }

        public int getColumnCount() {
            return 6;
        }

        public Object getValueAt(int i, int i1) {
            ContentRootTemplate template = m_roots.get(i);
            switch (i1) {
                case 0:
                    return template.getRootDirTemplate();
                case 1:
                    return template.getMainJavaDirTemplate();
                case 2:
                    return template.getTestJavaDirTemplate();
                case 3:
                    return template.getMainResourceDirTemplate();
                case 4:
                    return template.getTestResourceDirTemplate();
                case 5:
                    Pattern includedSubdirsPattern = template.getIncludedSubdirsPattern();
                    if (includedSubdirsPattern == null) {
                        return "";
                    } else {
                        return includedSubdirsPattern.pattern();
                    }
            }
            return null;
        }

        public boolean isCellEditable(int i, int i1) {
            return true;
        }

        public void setValueAt(Object object, int i, int i1) {
            ContentRootTemplate template = m_roots.get(i);
            String s = String.valueOf(object);
            switch (i1) {
                case 0:
                    template.setRootDirTemplate(s);
                    return;
                case 1:
                    template.setMainJavaDirTemplate(s);
                    return;
                case 2:
                    template.setTestJavaDirTemplate(s);
                    return;
                case 3:
                    template.setMainResourceDirTemplate(s);
                    return;
                case 4:
                    template.setTestResourceDirTemplate(s);
                    return;
                case 5:
                    if ("".equals(s)) {
                        template.setIncludedSubdirsPattern(null);
                    } else {
                        try {
                            template.setIncludedSubdirsPattern(Pattern.compile(s));
                        } catch (RuntimeException e) {
                            JOptionPane.showMessageDialog(IvyPluginConfiguration.this.m_rootPanel, e.getMessage(), "Regular Expression Error", JOptionPane.ERROR_MESSAGE);
                        }
                    }
            }
        }

    }
}
